package io.potato.task.config;

import java.io.IOException;
import java.io.Reader;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Response;
import feign.codec.ErrorDecoder;
import feign.jackson.JacksonDecoder;
import feign.okhttp.OkHttpClient;
import io.potato.core.util.Strings;
import io.potato.ts.sms.HuaweiSmsClient;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;

/**
 * Feign 接口配置
 * author: timl
 * time: 2018/12/8 10:12
 */

@Configuration
@Slf4j
public class FeignConfig {
	
	@Value("${sms.api-url}")
	private String apiUrl;

    @Bean
    public HuaweiSmsClient huaweiSmsClientBean() {

        //String apiUrl = "https://api.rtc.huaweicloud.com:10443";
        //apiUrl = "http://localhost:9100";
        log.info("init feigh. api url is " + apiUrl);
        return Feign.builder()
                //.encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .client(new OkHttpClient(okHttpClient()))
                .requestInterceptor(new HuaWeiSmsInterceptor())
                .errorDecoder(new HuaweiSmsErrorDecoder())
                //.logger(new Logger.JavaLogger().appendToFile("logs/feign.log"))
                //.logLevel(Logger.Level.FULL)
                .target(HuaweiSmsClient.class, apiUrl);
    }
    
    static class HuaweiSmsErrorDecoder implements ErrorDecoder {

		@Override
		public Exception decode(String methodKey, Response response) {
			try {
				Reader reader = response.body().asReader(Charset.forName("UTF-8"));
				CharBuffer buffer = CharBuffer.allocate(response.body().length());
				reader.read(buffer);
                String msg = "feign error: " + response.status() + " " + methodKey + " : " + buffer.toString();
                log.error(msg);
                return new Exception(msg);
			} catch (IOException e) {
                return new Exception(response.status() + " " + methodKey);
			}

		}
    	
    }
    
    /**
             *  添加华为短信接口的header
     * @author timl
     * created: 2019年1月8日 下午3:10:07
     */
    static class HuaWeiSmsInterceptor implements RequestInterceptor {
    	
    	static Charset UTF8 = Charset.forName("UTF-8");
        @Override 
        public void apply(RequestTemplate template) {
            template.header("accept", "application/json");
            template.header("Authorization", "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");   
            
            String body = template.requestBody().asString();
            if (!body.startsWith("{")) {
	            body = Strings.urlFormat(body);               
	            template.body(Request.Body.encoded(body.getBytes(UTF8), UTF8));
	            
            }
            //System.out.println(template.requestBody().asString());
        }
    }

    /**
     * 使用okhttp
     * @return
     */
    @Bean
    public okhttp3.OkHttpClient okHttpClient() {
        return new okhttp3.OkHttpClient.Builder()
                .connectionPool(new ConnectionPool(50, 10, TimeUnit.MINUTES))
                .connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(5, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .sslSocketFactory(sslSocketFactory(), x509TrustManager())       
                .hostnameVerifier(hostnameVerifier())
                .build();
    }   
    
    /**
     * https信任任何连接
     * @return
     */
    @Bean
    public X509TrustManager x509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }
    
    /**
     * https信任任何连接
     * @return
     */
    @Bean
    public SSLSocketFactory sslSocketFactory() {
        try {
            //信任任何链接
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    @Bean
    public HostnameVerifier hostnameVerifier() {
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        };
        return hostnameVerifier;
    }


}
